package com.ruoyi.system.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.mapper.TBaseBankMapper;
import com.ruoyi.system.mapper.TBaseCostMapper;
import com.ruoyi.system.service.ITBaseProjectDetailsService;
import com.ruoyi.system.service.ITSpCountIncomeService;
import com.ruoyi.system.service.ITSpCountTaxService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.TSpProjectDetailMapper;
import com.ruoyi.system.service.ITSpProjectDetailService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 项目收入支出流水Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-03-21
 */
@Service
public class TSpProjectDetailServiceImpl extends ServiceImpl<TSpProjectDetailMapper, TSpProjectDetail> implements ITSpProjectDetailService
{
    @Autowired
    private TSpProjectDetailMapper tSpProjectDetailMapper;

    @Autowired
    private ITSpCountIncomeService incomeService;

    @Autowired
    private ITSpCountTaxService taxService;

    @Autowired
    private ITBaseProjectDetailsService baseProjectDetailsService;

    @Autowired
    private TBaseBankMapper baseBankMapper;

    @Autowired
    private TBaseCostMapper baseCostMapper;

    /**
     * 查询项目收入支出流水
     * 
     * @param pdetailId 项目收入支出流水主键
     * @return 项目收入支出流水
     */
    @Override
    public TSpProjectDetail selectTSpProjectDetailByPdetailId(String pdetailId)
    {
        return tSpProjectDetailMapper.selectTSpProjectDetailByPdetailId(pdetailId);
    }

    /**
     * 查询项目收入支出流水列表
     * 
     * @param tSpProjectDetail 项目收入支出流水
     * @return 项目收入支出流水
     */
    @Override
    public List<TSpProjectDetail> selectTSpProjectDetailList(TSpProjectDetail tSpProjectDetail)
    {
        return tSpProjectDetailMapper.selectTSpProjectDetailList(tSpProjectDetail);
    }

    /**
     * 处理月数据
     * @param projectId
     * @param month
     * @param costId
     */
    public void processingMonthData (Long projectId,String month,Long costId){
        //每次添加 重新统计 当月数据
        Map<String, Object> map = tSpProjectDetailMapper.selectProjectDetailBycostId(projectId.toString(), month, costId.toString());
        TSpCountIncome income = new TSpCountIncome();
        income.setProjectId(projectId);
        income.setCountDate(month);
        income.setCostId(costId);
        income.setTotalMoney((BigDecimal) map.get("sumCostMoney"));
        income.setCreateDate(DateUtils.getNowDate());
        income.setCreatePerson("SYSTEM");
        incomeService.remove(new LambdaQueryWrapper<TSpCountIncome>()
                .eq(TSpCountIncome :: getProjectId,projectId)
                .eq(TSpCountIncome :: getCostId,costId)
                .eq(TSpCountIncome :: getCountDate,month));
        incomeService.save(income);
        this.processingTaxData(projectId,month);
    }

    /**
     * 处理项目税款利润统计表
     * @param projectId
     * @param month
     */
    public void processingTaxData(Long projectId,String month){
        List<Map<String, Object>> list = tSpProjectDetailMapper.selectProjectDetailByLastMonth(projectId.toString(), month);
        //收入合计
        BigDecimal incomeMoney = list.stream().filter(o -> "1".equals(o.get("cost_type"))).map(p -> (BigDecimal)p.get("sumCostMoney")).reduce(BigDecimal.ZERO,BigDecimal :: add);
        //支出合计
        BigDecimal payMoney = list.stream().filter(o -> "2".equals(o.get("cost_type"))).map(p -> (BigDecimal)p.get("sumCostMoney")).reduce(BigDecimal.ZERO,BigDecimal :: add);
        //项目周期明细表 取税率 和开票金额
        TBaseProjectDetails one = baseProjectDetailsService.getOne(new LambdaQueryWrapper<TBaseProjectDetails>()
                .eq(TBaseProjectDetails::getProjectId, projectId)
                .eq(TBaseProjectDetails::getCountDate, month));
        //税率
        BigDecimal taxRate = BigDecimal.ZERO;
        //开票金额
        BigDecimal billMoney = BigDecimal.ZERO;
        //税额
        BigDecimal taxMoney = BigDecimal.ZERO;
        if(ObjectUtil.isNotNull(one)){
            taxRate = one.getTaxRate();
            billMoney = one.getBillMoney();
            taxMoney = taxRate.multiply(billMoney).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
            payMoney = payMoney.add(taxMoney);
//            if(BigDecimal.ZERO.compareTo(taxRate) != 0 && BigDecimal.ZERO.compareTo(billMoney) != 0){
////                incomeMoney = incomeMoney.add(billMoney); //开票金额不算到收入合计里
//                taxMoney = taxRate.multiply(billMoney).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
//                payMoney = payMoney.add(taxMoney);
//            }
        }
        //利润合计
        BigDecimal profitMoney = incomeMoney.subtract(payMoney);
        //利润÷收入X100=利润率
        BigDecimal profitRate = (BigDecimal.ZERO.compareTo(incomeMoney) == 0 ? BigDecimal.ZERO : profitMoney.divide(incomeMoney, 3, BigDecimal.ROUND_HALF_UP)).multiply(new BigDecimal(100));
        TSpCountTax tax = new TSpCountTax();
        tax.setProjectId(projectId);
        tax.setCountDate(month);
        tax.setTaxRate(taxRate);
        tax.setBillMoney(billMoney);
        tax.setTaxMoney(taxMoney);
        tax.setIncomeMoney(incomeMoney);
        tax.setPayMoney(payMoney);
        tax.setProfitMoney(profitMoney);
        tax.setProfitRate(profitRate);
        tax.setCreateDate(DateUtils.getNowDate());
        tax.setCreatePerson("SYSTEM");
        taxService.remove(new LambdaQueryWrapper<TSpCountTax>()
                .eq(TSpCountTax :: getProjectId,projectId)
                .eq(TSpCountTax :: getCountDate,month));
        if(incomeMoney.compareTo(BigDecimal.ZERO) != 0 || payMoney.compareTo(BigDecimal.ZERO) != 0 ){
            taxService.save(tax);
        }
    }

    public static void main(String[] args) {
        BigDecimal incomeMoney = new BigDecimal(100);
        BigDecimal payMoney = new BigDecimal(0.4);
        BigDecimal profitMoney = incomeMoney.subtract(payMoney);
        //利润÷收入X100=利润率
        BigDecimal profitRate = (BigDecimal.ZERO.compareTo(incomeMoney) == 0 ? BigDecimal.ZERO : profitMoney.divide(incomeMoney, 3, BigDecimal.ROUND_HALF_UP)).multiply(new BigDecimal(100));
        System.out.println(profitRate);
    }

    /**
     * 处理之后的数据
     * @param tSpProjectDetail
     * @param bankExistMoney  当前银行余额
     * @param pdetailId id 刪除需要
     */
    private void processingAfterData(TSpProjectDetail tSpProjectDetail,BigDecimal bankExistMoney,String pdetailId){
        //上次余额
        BigDecimal bankExistMoneyLast =  bankExistMoney;

        List<TSpProjectDetail> tSpProjectDetails = tSpProjectDetailMapper.selectByAfterList(tSpProjectDetail.getBankId(), tSpProjectDetail.getCostDate(),pdetailId);
        if(tSpProjectDetails != null && tSpProjectDetails.size() > 0){
            List<TSpProjectDetail> detailList = new ArrayList<>();
            TSpProjectDetail detail ;
            for (TSpProjectDetail de : tSpProjectDetails) {
                String costType = de.getCostType();
                if ("1".equals(costType)){
                    bankExistMoneyLast = bankExistMoneyLast.add(de.getCostMoney());
                }
                if ("2".equals(costType)){
                    bankExistMoneyLast = bankExistMoneyLast.subtract(de.getCostMoney());
                }
                detail = new TSpProjectDetail();
                detail.setBankExistMoney(bankExistMoneyLast);
                detail.setPdetailId(de.getPdetailId());
                detailList.add(detail);
            }
            tSpProjectDetailMapper.bacthUpdateTSpProjectDetail(detailList);
        }
    }

    /**
     * 新增项目收入支出流水
     * 
     * @param tSpProjectDetail 项目收入支出流水
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertTSpProjectDetail(TSpProjectDetail tSpProjectDetail)
    {
        Long projectId = tSpProjectDetail.getProjectId();
        Long costId = tSpProjectDetail.getCostId();
        Long bankId = tSpProjectDetail.getBankId();
        Date costDate = tSpProjectDetail.getCostDate();
        String month = DateUtil.format(costDate, "yyyyMM");
        BigDecimal bankExistMoney = BigDecimal.ZERO;//银行余额
        TBaseCost cost = baseCostMapper.selectTBaseCostByCostId(costId);
        /**  1 处理银行余额 */
        TSpProjectDetail recently = tSpProjectDetailMapper.selectByRecently(bankId, costDate);//最近流水数据
        if(ObjectUtil.isNull(recently)){
            //第一条数据 记录初始余额
            TBaseBank tBaseBank = baseBankMapper.selectTBaseBankByBankId(bankId);
            bankExistMoney = tBaseBank.getInitMoney();
            if ("1".equals(cost.getCostType())){
                bankExistMoney = bankExistMoney.add(tSpProjectDetail.getCostMoney());
            }
            if ("2".equals(cost.getCostType())){
                bankExistMoney = bankExistMoney.subtract(tSpProjectDetail.getCostMoney());
            }
            tSpProjectDetail.setBankExistMoney(bankExistMoney);
        }else {
            if ("1".equals(cost.getCostType())){
                bankExistMoney = recently.getBankExistMoney().add(tSpProjectDetail.getCostMoney());
            }
            if ("2".equals(cost.getCostType())){
                bankExistMoney = recently.getBankExistMoney().subtract(tSpProjectDetail.getCostMoney());
            }
            tSpProjectDetail.setBankExistMoney(bankExistMoney);
        }
        int i = tSpProjectDetailMapper.insertTSpProjectDetail(tSpProjectDetail);
        /**  2 处理月数据 */
        this.processingMonthData(projectId,month,costId);
        /**  3 处理后续银行余额问题 */
        this.processingAfterData(tSpProjectDetail,bankExistMoney,tSpProjectDetail.getPdetailId());
        return i;
    }

    /**
     * 修改项目收入支出流水
     * 
     * @param tSpProjectDetail 项目收入支出流水
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateTSpProjectDetail(TSpProjectDetail tSpProjectDetail) {
        TSpProjectDetail detail = tSpProjectDetailMapper.selectTSpProjectDetailByPdetailId(tSpProjectDetail.getPdetailId());
        Long projectId = tSpProjectDetail.getProjectId();
        Long costId = tSpProjectDetail.getCostId();
        Long bankId = tSpProjectDetail.getBankId();
        Date costDate = tSpProjectDetail.getCostDate();
        String month = DateUtil.format(costDate, "yyyyMM");
        BigDecimal bankExistMoney = BigDecimal.ZERO;//银行余额
        TBaseCost cost = baseCostMapper.selectTBaseCostByCostId(costId);
        /**  1 处理银行余额 */
        TSpProjectDetail recently = tSpProjectDetailMapper.selectByRecentlyUpd(bankId, tSpProjectDetail.getPdetailId(),costDate);//最近流水数据
        if(ObjectUtil.isNull(recently)){
            //第一条数据 记录初始余额
            TBaseBank tBaseBank = baseBankMapper.selectTBaseBankByBankId(bankId);
            bankExistMoney = tBaseBank.getInitMoney();
            if ("1".equals(cost.getCostType())){
                bankExistMoney = bankExistMoney.add(tSpProjectDetail.getCostMoney());
            }
            if ("2".equals(cost.getCostType())){
                bankExistMoney = bankExistMoney.subtract(tSpProjectDetail.getCostMoney());
            }
            tSpProjectDetail.setBankExistMoney(bankExistMoney);
        }else {
            if ("1".equals(cost.getCostType())){
                bankExistMoney = recently.getBankExistMoney().add(tSpProjectDetail.getCostMoney());
            }
            if ("2".equals(cost.getCostType())){
                bankExistMoney = recently.getBankExistMoney().subtract(tSpProjectDetail.getCostMoney());
            }
            tSpProjectDetail.setBankExistMoney(bankExistMoney);
        }
        int i = tSpProjectDetailMapper.updateTSpProjectDetail(tSpProjectDetail);
        /**  2 处理月数据 */
        //如果修改费用类别  源类别 做统计处理
        if(!detail.getCostId().equals(costId)){
            String lastMonth = DateUtil.format(detail.getCostDate(), "yyyyMM");
            this.processingMonthData(projectId,lastMonth,detail.getCostId());
        }
        this.processingMonthData(projectId,month,costId);
        /**  3 处理后续银行余额问题 */
        this.processingAfterData(tSpProjectDetail,bankExistMoney,tSpProjectDetail.getPdetailId());
        /**  4 如果修改了收支实际日期  则二次处理后续银行余额*/
        if(tSpProjectDetail.getCostDate().getTime() > detail.getCostDate().getTime()){
            BigDecimal bankExistMoneyOld = BigDecimal.ZERO;//银行余额
            TBaseCost costOld = baseCostMapper.selectTBaseCostByCostId(detail.getCostId());
            if ("1".equals(costOld.getCostType())){
                bankExistMoneyOld = detail.getBankExistMoney().subtract(detail.getCostMoney());
            }
            if ("2".equals(costOld.getCostType())){
                bankExistMoneyOld = detail.getBankExistMoney().add(detail.getCostMoney());
            }
            this.processingAfterData(detail,bankExistMoneyOld,tSpProjectDetail.getPdetailId());
        }
        return i;
    }

    /**
     * 批量删除项目收入支出流水
     * 
     * @param pdetailIds 需要删除的项目收入支出流水主键
     * @return 结果
     */
    @Override
    public int deleteTSpProjectDetailByPdetailIds(String[] pdetailIds)
    {
        return tSpProjectDetailMapper.deleteTSpProjectDetailByPdetailIds(pdetailIds);
    }

    /**
     * 删除项目收入支出流水信息
     * 
     * @param pdetailId 项目收入支出流水主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteTSpProjectDetailByPdetailId(String pdetailId)
    {
        TSpProjectDetail tSpProjectDetail = tSpProjectDetailMapper.selectTSpProjectDetailByPdetailId(pdetailId);
        Long projectId = tSpProjectDetail.getProjectId();
        Long costId = tSpProjectDetail.getCostId();
        Long bankId = tSpProjectDetail.getBankId();
        Date costDate = tSpProjectDetail.getCostDate();
        String month = DateUtil.format(costDate, "yyyyMM");
        BigDecimal bankExistMoney = BigDecimal.ZERO;//银行余额
        TBaseCost cost = baseCostMapper.selectTBaseCostByCostId(costId);
        /**  1 处理银行余额 */
        TSpProjectDetail recently = tSpProjectDetailMapper.selectByRecentlyUpd(bankId, pdetailId,costDate);
        if(ObjectUtil.isNull(recently)){
            //第一条数据 记录初始余额
            TBaseBank tBaseBank = baseBankMapper.selectTBaseBankByBankId(bankId);
            bankExistMoney = tBaseBank.getInitMoney();
            tSpProjectDetail.setBankExistMoney(bankExistMoney);
        }else {//如果不是第一条 则取最近一条数据
            bankExistMoney = recently.getBankExistMoney();
        }
        int i = tSpProjectDetailMapper.deleteTSpProjectDetailByPdetailId(pdetailId);
        /**  2 处理月数据 */
        this.processingMonthData(projectId,month,costId);
        /**  3 处理后续银行余额问题 */
        this.processingAfterData(tSpProjectDetail,bankExistMoney,pdetailId);
        return i;
    }
}
